package cn.comon.app.scan.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.comon.app.scan.component.SysConfigBean;
import cn.comon.app.scan.entity.DubaRequest;
import cn.comon.app.scan.entity.NetqinRequest;
import cn.comon.app.scan.entity.TencentRequest;
import cn.comon.app.scan.service.analysis.IAnalysisScanResult;
import cn.comon.app.scan.util.SpringContextUtil;
import cn.comon.app.scan.util.UtilTools;

/**
 * 第三方软件检测回调接口响应
 */
@Controller
@RequestMapping("/callback.api/*")
public class AppScanController {
    private static Logger logger = Logger.getLogger(AppScanController.class.getName());
    public AppScanController() {
    }

    /**
     * 腾讯软件检测结果回调
     * @param map ModelMap
     * @param request 请求的对象
     * @return 返回的响应信息
     * @throws IOException 
     */
    @RequestMapping(value = "tencent",produces="text/html;charset=UTF-8")
    @ResponseBody //可将返回的内容直接输出，或者直接显示在页面
    public String checkResultTencent(ModelMap map, TencentRequest tencentRequest, HttpServletRequest request) {
        JSONObject result = new JSONObject();
        String authkey = tencentRequest.getAuthkey();
        String response = tencentRequest.getResponse();
        logger.info("【AppScanController.tencent callback authkey:" + authkey + "】");
        logger.info("【AppScanController.tencent callback response:" + response + "】");
        try {
            //请求ip是否合法
            String hostIP = UtilTools.getIpAddr(request);
            //检测
            String authkeyTMP = UtilTools.getStringMd5(response + SysConfigBean.getProperty("qq.channelId") + SysConfigBean.getProperty("qq.secureKey"));
            logger.info("【AppScanController.tencent authkeyTMP:" + authkeyTMP + "】");
            //第三方标识
            if (authkey == null || "".equals(authkey)) {
            	result.put("result", "error");
            	result.put("reason", "invalid auth");
            } else if (!MessageDigest.isEqual(authkeyTMP.getBytes(), authkey.getBytes())) {
            	result.put("result", "error");
            	result.put("reason", "invalid auth");
            } else if (response == null || "".equals(response)) {
                result.put("result", "error");
                result.put("reason", "invalid auth");
            } else {
                JSONObject resultData = JSONObject.fromObject(response);
                IAnalysisScanResult analysisScanResult = (IAnalysisScanResult) SpringContextUtil.getBean("qqAnalysisScanResultImpl");
                result = analysisScanResult.checkResult(resultData);
            }
        } catch (JSONException e) {
            logger.error(e);
            result.put("result", "error");
            result.put("reason", "invalid auth");
        } catch (Exception e) {
            logger.error(e);
            logger.error(e);
            result.put("result", "error");
        	result.put("reason", "unknown");
        } 
        map.put("result", result);
        return result.toString();
    }
    
    /**
     * 金山毒霸软件检测结果回调
     * @param map ModelMap
     * @param request 请求的对象
     * @return 返回的响应信息
     * @throws UnsupportedEncodingException
     */
    @RequestMapping(value = "duba",produces="text/html;charset=UTF-8")
    @ResponseBody
    public String checkResultDuba(ModelMap map, DubaRequest dubaRequest, HttpServletRequest request,HttpServletResponse response) {
        JSONObject result = new JSONObject();
        logger.info("【AppScanController.duba callback V:" + dubaRequest.getV() + "】");
        logger.info("【AppScanController.duba callback sign:" + dubaRequest.getSign() + "】");
        logger.info("【AppScanController.duba callback tpl:" + dubaRequest.getTpl() + "】");
        logger.info("【AppScanController.duba callback scanResult:" + dubaRequest.getScanResult() + "】");
        try {
            //error_code 1:参数错误，2:签名验证错误,3:未知异常
            if (dubaRequest.getV() == null || "".equals(dubaRequest.getV())) {
                result.put("error_code", "1");
            } else if (dubaRequest.getSign() == null || "".equals(dubaRequest.getSign())) {
                result.put("error_code", "1");
            } else if (dubaRequest.getScanResult() == null || "".equals(dubaRequest.getScanResult())) {
                result.put("error_code", "1");
            } else {
                //签名算法:
                //step1: 将所有输入参数（包括GET和POST参数，但除sign参数外）格式化为"key=value"格式，
                         //如"k1=v1"、"k2=v2"、 "k3=v3"；
                //step2: 将格式化好的参数键值对以字典序升序方式排列后，拼接在一起，如"k1=v1k2=v2k3=v3"；
                //step3: 在拼接好的字符串末尾拼接上我们为金山提供的secure_key，并对获取到的字符串算MD5签名，
                         //签名值即为sign参数的值。
                Map<String, String> mapTMP = new HashMap<String, String>();
                mapTMP.put("tpl", dubaRequest.getTpl());
                mapTMP.put("v", dubaRequest.getV());
                mapTMP.put("scanResult", dubaRequest.getScanResult());
                //升序方式排序
                TreeSet<String> ts = new TreeSet<String>();
                ts.add("tpl");
                ts.add("v");
                ts.add("scanResult");
                Iterator<String> iterator = ts.iterator();  
                //迭代器 
                String sign="";
                while(iterator.hasNext()) {
                    String strTMP = iterator.next();
                    sign = sign + strTMP + "="+ mapTMP.get(strTMP);
                }
                sign = sign + SysConfigBean.getProperty("duba.secureKey");
                logger.info("【AppScanController.duba】the value of sign from duba:" + sign);
                sign = UtilTools.getStringMd5(sign);
                logger.info("【AppScanController.duba】the value of signMD5 from duba:" + sign);
                if (!MessageDigest.isEqual(dubaRequest.getSign().getBytes(), sign.getBytes())) {
                    result.put("error_code", "2");
                    return result.toString();
                }
                
                JSONObject resultData = JSONObject.fromObject(dubaRequest.getScanResult());
                IAnalysisScanResult analysisScanResult = (IAnalysisScanResult) SpringContextUtil.getBean("dubaAnalysisScanResultImpl");
                result = analysisScanResult.checkResult(resultData);
            }
        } catch (JSONException e) {
            logger.error(e);
            result.put("error_code", "2");
        } catch (Exception e) {
            logger.error(e);
            result.put("error_code", "2");
        } 
        return result.toString();
    }
    
    /**
     * 网秦软件检测结果回调
     * @param map ModelMap
     * @param request 请求的对象
     * @return 返回的响应信息
     * @throws UnsupportedEncodingException 
     */
    @RequestMapping(value = "netq",produces="text/html;charset=UTF-8")
    @ResponseBody
    public String checkResultNetqin(ModelMap map, NetqinRequest netqinRequest, HttpServletRequest request) {
        String result = "200";
        logger.info("【AppScanController.netq callback callback:" + netqinRequest.getCallback() + "】");
        logger.info("【AppScanController.netq callback sid:" + netqinRequest.getSid() + "】");
        try {
            //获取网秦发送的检测结果请求信息
            logger.info("thi value of interface from Netqin =" + URLDecoder.decode(netqinRequest.getCallback(), "UTF-8"));
            
            String callback = "";
            String errcode = "";
            String authority = "";
            Document doc = DocumentHelper.parseText(netqinRequest.getCallback());
            Element rootElt = doc.getRootElement(); // 获取根节点
            callback = rootElt.elementTextTrim("callback"); ///获取根节点下的子节
            errcode = rootElt.elementTextTrim("errcode"); ///获取根节点下的子节
            if (UtilTools.convertNnllToString(errcode).equals("")) {

                JSONObject resultData = new JSONObject();
                resultData.put("callback", netqinRequest.getCallback());
                resultData.put("sid", netqinRequest.getSid());
                IAnalysisScanResult analysisScanResult = (IAnalysisScanResult) SpringContextUtil.getBean("netQinAnalysisScanResultImpl");
                analysisScanResult.checkResult(resultData);
                
            } else {
                //检测失败，该条检测信息的sid和检测错误code。
                logger.info("the error of callback from Netqin,sid=" + netqinRequest.getSid() + ";errorcode=" + errcode);
            }
            logger.info("callback from Netqin,callback=" + callback + ";sid=" + netqinRequest.getSid());
            logger.info("callback from Netqin,authority=" + authority + ";sid=" + netqinRequest.getSid());
        } catch (JSONException e) {
            logger.error(e);
        } catch (DocumentException e) {
            logger.error(e);
        } catch (Exception e) {
            logger.error(e);
        }
        map.put("result", result);
        return result;
    }
}